package com.goldenKey.user.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.goldenKey.common.component.AccountComponent;
import com.goldenKey.user.pojo.query.RegisterQuery;
import com.goldenKey.user.pojo.vo.AccountVo;
import com.goldenKey.common.component.RedisComponent;
import com.goldenKey.common.constant.Constant;
import com.goldenKey.common.exception.AppException;
import com.goldenKey.common.pojo.enumeration.ExceptionEnum;
import com.goldenKey.common.pojo.result.R;
import com.goldenKey.user.pojo.query.LoginQuery;
import com.goldenKey.user.service.IAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.io.IOException;


@RestController
@RequestMapping("/account")
@Validated
@Slf4j
public class AccountController {

    @Autowired
    private IAccountService accountService;
    @Resource
    private RedisComponent redisComponent;
    @Resource
    private AccountComponent accountComponent;



    /**
     * 发送邮箱验证码
     * @param toEmail
     * @return
     */
    @GetMapping("/sendEmail")
    public R<Void> sendCommonEmail(HttpSession session, @NotEmpty String toEmail) {
        accountComponent.sendCommonEmail(session, toEmail);
        return R.ok();
    }

    /**
     * 用户注册
     * @param registerQuery
     * @return
     */
    @PostMapping("/register")
    @Transactional
    public R<Void> register(@RequestBody RegisterQuery registerQuery, HttpSession session) {
        // 判断密码与确认密码是否一致
        if(!registerQuery.getPassword().equals(registerQuery.getConfirmPassword())) {
            throw new AppException(ExceptionEnum.PASSWORD_INCONSISTENCY);
        }

        // 获取 session 中存储的邮箱验证码
        String emailCode = (String) session.getAttribute(Constant.EMAIL_CODE_KEY);
        Long timestamp = (Long) session.getAttribute(Constant.EMAIL_CODE_TIMESTAMP_KEY);
        // 验证码是否过期（时间为2分钟）
        if(emailCode == null || System.currentTimeMillis() - timestamp > 2 * 60 * 1000) {
            throw new AppException(ExceptionEnum.CODE_EXPIRED);
        }
        // 验证验证码是否正确
        if (emailCode != null && !emailCode.equalsIgnoreCase(registerQuery.getEmailCode())) {
            throw new AppException(ExceptionEnum.CODE_ERROR);
        }

        // 操作合法，完成注册
        accountService.register(registerQuery);
        return R.ok();
    }

    /**
     * 生成图形验证码
     * @param response
     * @throws IOException
     */
    @GetMapping("/setCaptcha")
    public void setCaptcha(HttpServletResponse response) throws IOException {
        LineCaptcha captcha = CaptchaUtil.createLineCaptcha(100, 40, 4, 40);
        String captchaKey = redisComponent.saveCaptchaKey(captcha.getCode());

        // 设置验证码 Key 到响应头
        response.setHeader(Constant.CAPTCHA_KEY, captchaKey);

        captcha.write(response.getOutputStream());

    }


    /**
     * 用户登陆
     * @param loginQuery
     * @param request
     * @return
     */
    @PostMapping("/login")
    @Transactional
    public R<AccountVo> login(@Validated @RequestBody LoginQuery loginQuery, HttpServletRequest request) {
        // 验证验证码是否正确
        String captcha = redisComponent.getCaptcha(loginQuery.getCaptchaKey());
        if (captcha == null) {
            throw new AppException(ExceptionEnum.CODE_EXPIRED);
        } else if(!captcha.equalsIgnoreCase(loginQuery.getCaptcha())) {
            throw new AppException(ExceptionEnum.CODE_ERROR);
        }

        AccountVo accountVo = accountService.login(loginQuery, request);

        // 在缓存中设置用户token
        redisComponent.saveUserToken(accountVo.getUserId(), accountVo.getUserToken());
        return R.ok(accountVo);
    }

    /**
     * 用户退出登录
     * @param userId
     * @return
     */
    @PostMapping("/logout")
    public R<Void> logout(@NotEmpty String userId) {

        // 删除缓存中的token
        redisComponent.deleteUserToken(userId);
        return R.ok();
    }

    /**
     * 判断用户表某个字段是否存在该值
     *
     * @param field
     * @param value
     * @return
     */
    @GetMapping("/checkIsExist")
    public R<Boolean> checkIsExist(@NotEmpty String field, @NotEmpty String value) {
        boolean result = accountService.checkIsExist(field, value);
        return R.ok(result);

    }

}

